using System;

using System.Web.UI.WebControls;
using System.Web.UI;
using System.ComponentModel;
using System.Drawing;
using Library.WebControls.SimpleButton;
using System.IO;

namespace Library.WebControls.SimpleUpload {
	[ToolboxBitmap(typeof(SpUpload), "Library.WebControls.SimpleUpload.SPUpload.bmp")]
	[Designer(typeof(SpUploadDesign))]
	[SupportsEventValidation]
	[DesignTimeVisible(true)]
	[ToolboxData("<{0}:SpUpload runat=server></{0}:SpUpload>")]
	public class SpUpload : BaseAjaxControl {
		public SpUpload() {
			//CssFileName = BaseCssDir + "spupload-ui.css";
			ClientScript = new ClientScript();
			AutoDeleteFile = true;
		}
		private string _cssFileName = BaseCssDir + "spupload-ui.css";
		[DefaultValue("~/style/simple/spupload-ui.css")]
		public override string CssFileName {
			get { return _cssFileName; }
			set {
				_cssFileName = value;
			}
		}
		private bool _isCallback;
		private bool _isParting;
		public override bool IsCallback {
			get {
				return _isCallback;
			}
		}
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[MergableProperty(false)]
		[Category("Data")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[DefaultValue("")]
		public ClientScript ClientScript {
			private set;
			get;
		}

		private static readonly Type UploadType = typeof(SpUpload);
		protected const string SpUploadCallbackParameter = "__SPUPLOADRQP_";
		protected const string SpUploadUserParameter = "__SPUPLOADCP_";
		protected const string SpUploadCallbackServerId = "__SPUPLOADS_";
		protected const string SpUploadPart = "__SPUPLOADIP_";
		protected const string SpUploadFileName = "__SPUPLOADFN_";
		protected const string SpUploadClientFileName = "__SPUPLOADCFN_";
		public static bool IsSpUploadCallback(Page page) {
			try {
				return page.Request[SpUploadCallbackParameter] == "T";
			} catch { return false; }

		}


		protected override void OnInit(EventArgs e) {
			base.OnInit(e);
			_isCallback = IsSpUploadCallback(Page) && Request[SpUploadCallbackServerId] == _divMainUpload.FileUpload.ClientID + "clone";
			if (_isCallback) {
				_isParting = Request[SpUploadPart] == "T";
			}
		}

		protected override void OnLoad(EventArgs e) {
			base.OnLoad(e);
			if (IsCallback) {
				if (_isParting) {
					if (Request.Files.Count > 0) {
						var file = Request.Files[0];
						var fileName = Request[SpUploadFileName];
						if (String.IsNullOrEmpty(fileName)) {
							fileName = DateTime.Now.Ticks.ToString();
						}
						var path = Path.Combine(Request.MapPath(ServerTempPath), fileName);
						FileStream fileStream = null;
						if (!File.Exists(path)) {
							fileStream = File.Create(path);
						} else {
							fileStream = File.OpenWrite(path);
						}
						using (fileStream) {
							if (fileStream.CanSeek) fileStream.Seek(0, SeekOrigin.End);
							const int chunkRead = 1024 * 10;
							//int bytesRead = 0;
							var bs = new byte[chunkRead];
							int readed = file.InputStream.Read(bs, 0, chunkRead);
							do {
								if (readed == 0) {
									break;
								}
								fileStream.Write(bs, 0, readed);
								readed = file.InputStream.Read(bs, 0, chunkRead);
							} while (readed > 0);
						}
						ProcessCustomCallbackEventArgs(new CustomCallbackEventArgs(String.Empty) { Result = fileName });
					}
				} else {
					string parameter = Request[SpUploadUserParameter];
					var u = new FileUploadCompleteEventArgs(parameter);
					var fileName = Request[SpUploadFileName];
					if (String.IsNullOrEmpty(fileName)) {
						if (Request.Files.Count > 0) {
							u.PostFile = Request.Files[0];
						}
					} else {
						u.UploadedServerFilePath = Path.Combine(Request.MapPath(ServerTempPath), fileName);
						var clientFileName = Request[SpUploadClientFileName];
						if (!String.IsNullOrEmpty(clientFileName)) {
							u.ClientFileName = Path.GetFileName(clientFileName);
						} else {
							u.ClientFileName = String.Empty;
						}

					}
					OnFileUploadComplete(u);
					if (!String.IsNullOrEmpty(fileName)) {
						if (AutoDeleteFile) {
							try {
								File.Delete(u.UploadedServerFilePath);
							} catch {
							}
						}
					}
				}
			}

			IncludeScriptOnLoad(UploadType, "Upload", "Library.WebControls.SimpleUpload.include.SpUpload.js", UtilLib);
		}


		protected virtual void OnFileUploadComplete(FileUploadCompleteEventArgs e) {
			var handler = FileUploadComplete;
			if (handler != null) {
				try {
					handler(this, e);
					ProcessCustomCallbackEventArgs(e);
				} catch (Exception ex) {
					WriteError(ex);
				}
			}
		}


		//private FileUpload _fileUpload;
		//private SpButton _uploadButton;
		[Description("Button for upload control")]
		[PersistenceMode(PersistenceMode.InnerProperty)]
		[MergableProperty(false)]
		[Category("Data")]
		[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
		[DefaultValue("")]
		public SpButton UploadButton {
			get {
				EnsureChildControls();
				return _divMainUpload.ButtonUpload;
			}
		}
		/// <summary>
		/// Server temp path for parting upload (HTML 5)
		/// </summary>
		public string ServerTempPath { get; set; }

		//private TextBox _textUpload;
		DivUpload _divMainUpload;
		protected override void CreateChildControls() {
			_divMainUpload = new DivUpload();
			//_divMainUpload = new HtmlGenericControl("div");
			//_divMainUpload.Attributes["class"] = "spupload";

			//_fileUpload = new FileUpload();
			//_fileUpload.Attributes["size"] = "1";
			//_fileUpload.CssClass = "sphiddenupload";
			//var divInput = new HtmlGenericControl("div");
			//_divMainUpload.Controls.Add(divInput);
			//divInput.Attributes["class"] = "spuploadText";
			//_textUpload = new TextBox {Enabled = false};
			//divInput.Controls.Add(_textUpload);
			//var divButton = new HtmlGenericControl("div");
			//divButton.Attributes["class"] = "spuploadbutton";
			//_uploadButton = new SpButton();
			//divButton.Controls.Add(_uploadButton);
			//_uploadButton.DivButton.Controls.Add(_fileUpload);
			//_divMainUpload.Controls.Add(divButton);
			Controls.Add(_divMainUpload);

		}


		/// <summary>
		/// support extension, split by ';' char
		/// </summary>
		public string SupportedExtension {
			get;
			set;
		}
		public string UnknowExtensionText { get; set; }
		/// <summary>
		/// Message is shown when file extension is not belong to extension determine.
		/// Message format: Extension is not supported. Only support:
		/// </summary>
		public string SupportExtensionText { get; set; }

		public override string ClientID {
			get {
				EnsureChildControls();
				return _divMainUpload.ClientID;
			}
		}

		public override string ID {
			get {
				EnsureChildControls();
				return _divMainUpload.ID;
			}
			set {
				EnsureChildControls();
				_divMainUpload.ID = value;
			}
		}

		public override string ClientName {
			get {
				EnsureChildControls();
				return base.ClientName;
			}
			set {
				EnsureChildControls();
				base.ClientName = value;
				_divMainUpload.ButtonUpload.ClientName = value + "_ulb";
			}
		}

		private const int ChSize = 1024 * 256;
		private int _chunkSize = ChSize;
		/// <summary>
		/// Chunk size bytes in upload
		/// </summary>
		[DefaultValue(ChSize)]

		public int ChunkSize {
			get { return _chunkSize; }
			set {
				if (value > 0) {
					_chunkSize = value;
				}
			}
		}

		public event EventHandler<FileUploadCompleteEventArgs> FileUploadComplete;

		protected override void CreateClientObjectAtRender(HtmlTextWriter writer) {
			var supportExtension = SupportedExtension;
			if (supportExtension == null) supportExtension = String.Empty;
			var unknowText = UnknowExtensionText;
			if (unknowText == null) unknowText = "Unknow extension";
			unknowText = unknowText.Replace('\'', '"').Replace('\\', '/');
			var supportText = SupportExtensionText;
			if (supportText == null) supportText = "Allow only extionsions:";
			supportText = supportText.Replace('\'', '"').Replace('\\', '/');
			BeginScriptTag(writer);
			writer.Write(String.Format("var {0}=new SpUpload('{0}','{1}','{2}','{3}','{4}','{5}','{6}',{7});",
				ClientName,
				_divMainUpload.TextUpload.ClientID,
				_divMainUpload.FileUpload.ClientID,
				_divMainUpload.ButtonUpload.ClientID,
				supportExtension.ToLower(),
				unknowText,
				supportText, ChunkSize));

			AddScriptHandler(writer, 1, ClientScript.TextChanged, "AddHandler");
			AddScriptHandler(writer, 3, ClientScript.BeforeCallback, "AddHandler");
			AddScriptHandler(writer, 4, ClientScript.PartUploadComplete, "AddHandler");
			EndScriptTag(writer);
		}
		protected override void Render(HtmlTextWriter writer) {
			if (!Visible) return;

			if (IsCallback) {
				Response.ContentEncoding = System.Text.Encoding.UTF8;
				Response.HeaderEncoding = System.Text.Encoding.UTF8;
				WriteCustomCallbackCompleteResult();
				FlushAndEndCallback();
			} else {
				_divMainUpload.FileUpload.Attributes["onchange"] = ClientName + ".Call(1)";

				_divMainUpload.ButtonUpload.DivButton.Attributes["onmousemove"] = ClientName + ".Call(2,event);";
				base.Render(writer);
			}
		}

		[DefaultValue("")]
		public Unit Width {
			get {
				EnsureChildControls();
				return new Unit(_divMainUpload.Style[HtmlTextWriterStyle.Width]);//.TextUpload.Width;
			}
			set {
				EnsureChildControls();
				//_divMainUpload.TextUpload.Width = value;
				_divMainUpload.Style[HtmlTextWriterStyle.Width] = value.ToString();

			}
		}
		[DefaultValue(typeof(Color), "")]
		[TypeConverter(typeof(WebColorConverter))]
		public Color BackColor {
			get {
				EnsureChildControls();
				return _divMainUpload.TextUpload.BackColor;
			}
			set {
				EnsureChildControls();
				_divMainUpload.TextUpload.BackColor = value;
			}
		}
		[DefaultValue(typeof(Color), "")]
		[TypeConverter(typeof(WebColorConverter))]
		public Color BorderColor {
			get {
				EnsureChildControls();
				return _divMainUpload.TextUpload.BorderColor;
			}
			set {
				EnsureChildControls();
				_divMainUpload.TextUpload.BorderColor = value;
			}
		}

		public BorderStyle BorderStyle {
			get {
				EnsureChildControls();
				return _divMainUpload.TextUpload.BorderStyle;
			}
			set {
				EnsureChildControls();
				_divMainUpload.TextUpload.BorderStyle = value;

			}
		}

		public FontInfo Font {
			get {
				EnsureChildControls();
				return _divMainUpload.TextUpload.Font;
			}
		}
		[DefaultValue(typeof(Color), "")]
		[TypeConverter(typeof(WebColorConverter))]
		public Color ForeColor {
			get {
				EnsureChildControls();
				return _divMainUpload.TextUpload.ForeColor;
			}
			set {
				EnsureChildControls();
				_divMainUpload.TextUpload.ForeColor = value;

			}
		}
		/// <summary>
		/// Auto delelete chunk file after fired Upload complete event
		/// </summary>
		[DefaultValue(true)]
		public bool AutoDeleteFile { get; set; }
		public Unit BorderWidth {
			get {
				EnsureChildControls();
				return _divMainUpload.TextUpload.BorderWidth;
			}
			set {
				EnsureChildControls();
				_divMainUpload.TextUpload.BorderWidth = value;

			}
		}
	}
}
